﻿using Core.CurrentFramework.infrastructure.interfaces;
using Core.CurrentFramework.Repository.Entity;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;

namespace Core.CurrentFramework.infrastructure
{
    public class DBBaseCore : IDBBaseCore
    {
        private readonly CurrentDbContext _context;

        public DBBaseCore(CurrentDbContext context)
        {
            this._context = context;
        }


        public int Add<T>(T model) where T : class
        {
            _context.Set<T>().Add(model);
            //保存成功后，会将自增的id设置给model的主键属性，并返回受影响的行数。
            return _context.SaveChanges();
        }




        public T AddReturnModel<T>(T model) where T : class
        {
            _context.Set<T>().Add(model);
            _context.SaveChanges();
            return model;
        }




        public int Delete<T>(T model) where T : class
        {
            _context.Set<T>().Remove(model);
            return _context.SaveChanges();
        }


        public int DelBy<T>(Expression<Func<T, bool>> delWhere) where T : class
        {
            //2.1.1 查询要删除的数据
            List<T> listDeleting = _context.Set<T>().Where(delWhere).ToList();
            //2.1.2 将要删除的数据 用删除方法添加到 EF 容器中
            listDeleting.ForEach(u =>
            {
                _context.Set<T>().Attach(u);  //先附加到EF 容器
                _context.Set<T>().Remove(u); //标识为删除状态
            });
            //2.1.3 一次性生成sql语句 到数据库执行删除
            return _context.SaveChanges();
        }





        public IQueryable<T> GetModel<T>() where T : class
        {
            return _context.Set<T>().AsQueryable();
        }


        public T GetModel<T>(Expression<Func<T, bool>> whereLambda) where T : class
        {
            return _context.Set<T>().Where(whereLambda).AsNoTracking().FirstOrDefault();
        }


        public T GetModel<TKey, T>(Expression<Func<T, bool>> whereLambda, Expression<Func<T, TKey>> orderLambda, bool isAsc = true) where T : class
        {
            if (isAsc)
            {
                return _context.Set<T>().Where(whereLambda).OrderBy(orderLambda).AsNoTracking().FirstOrDefault();
            }
            else
            {
                return _context.Set<T>().Where(whereLambda).OrderByDescending(orderLambda).AsNoTracking().FirstOrDefault();
            }
        }


        public List<T> GetListBy<T>(Expression<Func<T, bool>> whereLambda) where T : class
        {
            return _context.Set<T>().Where(whereLambda).AsNoTracking().ToList();
        }


        public List<T> GetListBy<TKey, T>(Expression<Func<T, bool>> whereLambda, Expression<Func<T, TKey>> orderLambda, bool isAsc = true) where T : class
        {

            if (isAsc)
            {
                return _context.Set<T>().Where(whereLambda).OrderBy(orderLambda).AsNoTracking().ToList();
            }
            else
            {
                return _context.Set<T>().Where(whereLambda).OrderByDescending(orderLambda).AsNoTracking().ToList();
            }
        }


        public List<T> GetPagedList<TKey, T>(int pageIndex, int pageSize, Expression<Func<T, bool>> whereLambda, Expression<Func<T, TKey>> orderByLambda, bool isAsc = true) where T : class
        {
            // 分页 一定注意： Skip 之前一定要 OrderBy
            if (isAsc)
            {
                return _context.Set<T>().Where(whereLambda).OrderBy(orderByLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize).AsNoTracking().ToList();
            }
            else
            {
                return _context.Set<T>().Where(whereLambda).OrderByDescending(orderByLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize).AsNoTracking().ToList();
            }
        }

        public List<T> GetPagedList<TKey, T>(int pageIndex, int pageSize, ref int rowCount, Expression<Func<T, bool>> whereLambda, Expression<Func<T, TKey>> orderByLambda, bool isAsc = true) where T : class
        {
            rowCount = _context.Set<T>().Where(whereLambda).Count();
            if (isAsc)
            {
                return _context.Set<T>().OrderBy(orderByLambda).Where(whereLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize).AsNoTracking().ToList();
            }
            else
            {
                return _context.Set<T>().OrderByDescending(orderByLambda).Where(whereLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize).AsNoTracking().ToList();
            }
        }

        public List<T> GetPagedList<TKey1, TKey2, T>(int pageIndex, int pageSize, ref int rowCount, Expression<Func<T, bool>> whereLambda, Expression<Func<T, TKey1>> orderByLambda1, Expression<Func<T, TKey2>> orderByLambda2, bool isAsc1 = true, bool isAsc2 = true) where T : class
        {
            rowCount = _context.Set<T>().Where(whereLambda).Count();
            if (isAsc1)
            {
                if (isAsc2)
                {
                    return _context.Set<T>().OrderBy(orderByLambda1).ThenBy(orderByLambda2).Where(whereLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize).AsNoTracking().ToList();
                }
                else
                {
                    return _context.Set<T>().OrderBy(orderByLambda1).ThenByDescending(orderByLambda2).Where(whereLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize).AsNoTracking().ToList();
                }
            }
            else
            {
                if (isAsc2)
                {
                    return _context.Set<T>().OrderByDescending(orderByLambda1).ThenBy(orderByLambda2).Where(whereLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize).AsNoTracking().ToList();
                }
                else
                {
                    return _context.Set<T>().OrderByDescending(orderByLambda1).ThenByDescending(orderByLambda2).Where(whereLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize).AsNoTracking().ToList();
                }
            }
        }

        public int Modify<T>(T model) where T : class
        {
            _context.Set<T>().Update(model);
            return _context.SaveChanges();
        }





    }
}
